﻿using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;

namespace Blackbird.Core.Editable.Base {
    public abstract class EditableEntityCollection<T> : BaseEditableEntity, INotifyCollectionChanged, IList<T>
        where T : class, IEditableEntity, new() {
        protected EditableEntityCollection() {
            Items = new ObservableCollection<T>();
            Items.CollectionChanged += ListCollectionChanged;
        }

        private T _selectedItem;
        /// <summary>
        /// Gets the SelectedItem property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public T SelectedItem {
            get { return _selectedItem; }
            set {
                if ((_selectedItem == value) || !Contains(value)) {
                    return;
                }
                _selectedItem = value;
                InvokePropertyChanged("SelectedItem");
            }
        }

        public ObservableCollection<T> Items { get; protected set; }

        public bool RaisesItemChangedEvents {
            get { return true; }
        }

        public virtual void DeleteSelected() {
            if (SelectedItem != null)
                Remove(SelectedItem);
        }

        public virtual T NewChild(object param) {
            var newChild = (T)param ?? new T();

            newChild.Name = string.Format(Common.Properties.Resources.UntitledEntityFormat, newChild.TypeName);
            newChild.Initialize();
            Add(newChild);

            return newChild;
        }

        #region IList<T> Members

        public int IndexOf(T item) {
            return Items.IndexOf(item);
        }

        public void Insert(int index, T item) {
            Items.Insert(index, item);
        }

        public void RemoveAt(int index) {
            Items.RemoveAt(index);
        }

        public T this[int index] {
            get { return Items[index]; }
            set { Items[index] = value; }
        }

        public void Add(T item) {
            if (!Items.Contains(item))
                Items.Add(item);

            SelectedItem = item;
        }

        public void Clear() {
            Items.Clear();
        }

        public bool Contains(T item) {
            return Items.Contains(item);
        }

        public void CopyTo(T[] array, int arrayIndex) {
            Items.CopyTo(array, arrayIndex);
        }

        public int Count {
            get { return Items.Count; }
        }

        public bool IsReadOnly {
            get { return false; }
        }

        public bool Remove(T item) {
            return Items.Remove(item);
        }

        public IEnumerator<T> GetEnumerator() {
            return Items.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator() {
            return GetEnumerator();
        }

        #endregion

        #region INotifyCollectionChanged Members

        public event NotifyCollectionChangedEventHandler CollectionChanged {
            add { Items.CollectionChanged += value; }
            remove { Items.CollectionChanged -= value; }
        }

        #endregion

        private void ListCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
            IsDirty = true;
        }
    }
}